
/**
 * This file is a part of qloudgen-sec. 
 * You can redistribute qloudgen-sec and/or modify it under the terms of the Lesser GNU General Public License version 3. 
 * qloudgen-sec is distributed WITHOUT ANY WARRANTY. 
 *
 * See the Lesser GNU General Public License for more details at http://www.gnu.org/licenses/. 
 **/
package org.qloudgen.sec.cas.management.serviceregistry.mongo;

import java.util.List;
import java.util.Random;

import javax.validation.constraints.NotNull;

import org.jasig.cas.services.AbstractRegisteredService;
import org.jasig.cas.services.LogoutType;
import org.jasig.cas.services.RegexRegisteredService;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.ServiceRegistryDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

/**
 * Implementation of <code>ServiceRegistryDao</code> that uses a MongoDb repository as the backend persistence mechanism.
 *
 *
 * @author mike
 */
@Repository
public final class MongoServiceRegistryDao implements ServiceRegistryDao, InitializingBean {

	private static final Logger logger = LoggerFactory.getLogger(MongoServiceRegistryDao.class);

	private static final String MONGODB_COLLECTION_NAME = RegisteredService.class.getSimpleName();

	private String collectionName = MONGODB_COLLECTION_NAME;

	private boolean dropCollection = false;
  
	@Autowired
	@NotNull
	private final MongoOperations mongoTemplate = null;

	@Override
	public void afterPropertiesSet() throws Exception {
		if (this.dropCollection) {
			logger.debug("Dropping database collection: {}", this.collectionName);
			this.mongoTemplate.dropCollection(this.collectionName);
		}

		if (!this.mongoTemplate.collectionExists(this.collectionName)) {
				logger.debug("Creating database collection: {}", this.collectionName);
				this.mongoTemplate.createCollection(this.collectionName);
  	}
		
		if (this.mongoTemplate.count(new Query(),this.collectionName) == 0){
					RegexRegisteredService service = new RegexRegisteredService();
					service.setDescription("Allows HTTP(S) and IMAP(S) protocols");
					service.setServiceId("^(https?|imaps?)://.*");
					service.setName("HTTP and IMAP");
					service.setAllowedToProxy(false);
					service.setEnabled(true);
					service.setSsoEnabled(true);
					service.setAnonymousAccess(false);
					service.setIgnoreAttributes(false);
					service.setEvaluationOrder(10000);
					service.setLogoutType(LogoutType.BACK_CHANNEL);
					service.setId(Math.abs((new Random()).nextLong()));
					this.mongoTemplate.save((RegisteredService)service, this.collectionName);
		}
		logger.debug("Creating default service : {}", this.mongoTemplate.count(new Query(),this.collectionName));
	}

	@Override
	@Transactional(readOnly = false)
	public boolean delete(final RegisteredService svc) {
		if (this.findServiceById(svc.getId()) != null) {
			this.mongoTemplate.remove(svc, this.collectionName);
			logger.debug("Removed registered service: {}", svc);
			return true;
		}
		return false;
	}

	@Override
	@Transactional(readOnly = true)
	public RegisteredService findServiceById(final long svcId) {
		return this.mongoTemplate.findOne(new Query(Criteria.where("id").is(svcId)), RegisteredService.class, this.collectionName);
	}

	@Override
	@Transactional(readOnly = true)
	public List<RegisteredService> load() {
		return this.mongoTemplate.findAll(RegisteredService.class, this.collectionName);
	}

	@Override
	@Transactional(readOnly = false)
	public RegisteredService save(final RegisteredService svc) {
    if (svc.getId() == -1) {
        ((AbstractRegisteredService) svc).setId(svc.hashCode());
    }
    /**
     * modify by maojun:cas RegisteredService id can not change,it is not uid,why this??
     * so we generate id by ourself.
    **/
    //((AbstractRegisteredService) svc).setId(Long.parseLong(this.getId()));
    
    ((AbstractRegisteredService) svc).setId(Math.abs((new Random()).nextLong()));
    
		logger.debug("***************************");
		logger.debug("service id is " + svc.getId());
		logger.debug("***************************");
		/**
		  modify end
		**/
		this.mongoTemplate.save(svc, this.collectionName);
		logger.debug("Saved registered service: {}", svc);
		return this.findServiceById(svc.getId());
	}

	/**
	 * Optionally, specify the name of the mongodb collection where services are to be kept.
	 * By default, the name of the collection is specified by the constant {@link #MONGODB_COLLECTION_NAME}
	 */
	public void setCollectionName(final String name) {
		this.collectionName = name;
	}

	/**
	 * When set to true, the collection will be dropped first before proceeding with other operations.
	 */
	public void setDropCollection(final boolean dropCollection) {
		this.dropCollection = dropCollection;
	}
	
}
